﻿using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text;
using System.Text.Json;

namespace WeatherMcpServer.Tools
{
    [McpServerToolType]
    public class WeatherTool
    {
        private readonly HttpClient _httpClient;
        private readonly IMemoryCache _cache;
        private readonly ILogger<WeatherTool> _logger;
        private const string ApiKey = "d962e180c8154f79bf055138250109";

        public WeatherTool(IHttpClientFactory httpClientFactory, IMemoryCache cache, ILogger<WeatherTool> logger)
        {
            _httpClient = httpClientFactory.CreateClient();
            _cache = cache;
            _logger = logger;
        }

        [McpServerTool(Name = "get-current-weather")]
        [Description("获取指定坐标的当前天气信息")]
        public async Task<string> GetCurrentWeatherAsync(
            [Description("纬度，范围-90到90")] double latitude,
            [Description("经度，范围-180到180")] double longitude)
        {
            if (latitude < -90 || latitude > 90)
                return "错误：纬度必须在-90到90之间";

            if (longitude < -180 || longitude > 180)
                return "错误：经度必须在-180到180之间";

            var cacheKey = $"current_{latitude}_{longitude}";

            try
            {
                if (_cache.TryGetValue(cacheKey, out string? cachedResult) && cachedResult != null)
                {
                    _logger.LogInformation("从缓存获取天气数据");
                    return cachedResult;
                }

                var url = $"http://api.weatherapi.com/v1/current.json?key={ApiKey}&q={latitude},{longitude}&aqi=no";

                _logger.LogInformation($"调用天气API: {url}");

                var response = await _httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();

                var content = await response.Content.ReadAsStringAsync();
                _logger.LogInformation($"API响应: {content}");

                // 使用JsonDocument进行更灵活的解析
                using var doc = JsonDocument.Parse(content);
                var root = doc.RootElement;

                var result = FormatCurrentWeather(root);

                // 缓存5分钟
                _cache.Set(cacheKey, result, TimeSpan.FromMinutes(5));

                return result;
            }
            catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
            {
                return "请求过于频繁，请稍后重试";
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "天气API请求失败");
                return $"网络请求失败: {ex.Message}";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取天气数据时发生错误");
                return $"获取天气数据失败: {ex.Message}";
            }
        }

        [McpServerTool(Name = "get-forecast")]
        [Description("获取指定坐标的3天天气预报")]
        public async Task<string> GetForecastAsync(
            [Description("纬度，范围-90到90")] double latitude,
            [Description("经度，范围-180到180")] double longitude)
        {
            if (latitude < -90 || latitude > 90)
                return "错误：纬度必须在-90到90之间";

            if (longitude < -180 || longitude > 180)
                return "错误：经度必须在-180到180之间";

            var cacheKey = $"forecast_{latitude}_{longitude}";

            try
            {
                if (_cache.TryGetValue(cacheKey, out string? cachedResult) && cachedResult != null)
                {
                    _logger.LogInformation("从缓存获取预报数据");
                    return cachedResult;
                }

                var url = $"http://api.weatherapi.com/v1/forecast.json?key={ApiKey}&q={latitude},{longitude}&days=3&aqi=no&alerts=no";

                _logger.LogInformation($"调用天气预报API: {url}");

                var response = await _httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();

                var content = await response.Content.ReadAsStringAsync();
                _logger.LogInformation($"API响应: {content}");

                // 使用JsonDocument进行更灵活的解析
                using var doc = JsonDocument.Parse(content);
                var root = doc.RootElement;

                var result = FormatForecast(root);

                // 缓存30分钟
                _cache.Set(cacheKey, result, TimeSpan.FromMinutes(30));

                return result;
            }
            catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
            {
                return "请求过于频繁，请稍后重试";
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "天气预报API请求失败");
                return $"网络请求失败: {ex.Message}";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取天气预报数据时发生错误");
                return $"获取天气预报失败: {ex.Message}";
            }
        }

        private static string FormatCurrentWeather(JsonElement root)
        {
            try
            {
                var location = root.GetProperty("location");
                var current = root.GetProperty("current");

                var sb = new StringBuilder();
                sb.AppendLine($"📍 位置: {location.GetProperty("name").GetString()}, {location.GetProperty("country").GetString()}");
                sb.AppendLine($"🌡️ 当前温度: {current.GetProperty("temp_c").GetDouble()}°C ({current.GetProperty("temp_f").GetDouble()}°F)");
                sb.AppendLine($"🤔 体感温度: {current.GetProperty("feelslike_c").GetDouble()}°C");
                sb.AppendLine($"💧 湿度: {current.GetProperty("humidity").GetInt32()}%");
                sb.AppendLine($"🌬️ 风速: {current.GetProperty("wind_kph").GetDouble()} km/h, {current.GetProperty("wind_dir").GetString()}");
                sb.AppendLine($"☁️ 天气状况: {current.GetProperty("condition").GetProperty("text").GetString()}");
                sb.AppendLine($"👀 能见度: {current.GetProperty("vis_km").GetDouble()} km");

                if (current.TryGetProperty("last_updated", out var lastUpdated))
                {
                    sb.AppendLine($"🌄 更新时间: {lastUpdated.GetString()}");
                }

                return sb.ToString();
            }
            catch (KeyNotFoundException ex)
            {
                return $"解析天气数据时缺少字段: {ex.Message}";
            }
        }

        private static string FormatForecast(JsonElement root)
        {
            try
            {
                var location = root.GetProperty("location");
                var forecast = root.GetProperty("forecast");
                var forecastDays = forecast.GetProperty("forecastday");

                var sb = new StringBuilder();
                sb.AppendLine($"📍 位置: {location.GetProperty("name").GetString()}, {location.GetProperty("country").GetString()}");
                sb.AppendLine();
                sb.AppendLine("📅 未来3天天气预报:");
                sb.AppendLine();

                foreach (var dayElement in forecastDays.EnumerateArray().Take(3))
                {
                    var day = dayElement.GetProperty("day");
                    var date = dayElement.GetProperty("date");
                    var astronomy = dayElement.GetProperty("astro");

                    sb.AppendLine($"📆 {date.GetDateTime():yyyy-MM-dd (ddd)}");
                    sb.AppendLine($"   🌡️ 温度: {day.GetProperty("mintemp_c").GetDouble()}°C - {day.GetProperty("maxtemp_c").GetDouble()}°C");
                    sb.AppendLine($"   ☀️ 天气: {day.GetProperty("condition").GetProperty("text").GetString()}");
                    sb.AppendLine($"   💧 湿度: {day.GetProperty("avghumidity").GetDouble()}%");
                    sb.AppendLine($"   🌬️ 风速: {day.GetProperty("maxwind_kph").GetDouble()} km/h");
                    sb.AppendLine($"   🌅 日出: {astronomy.GetProperty("sunrise").GetString()}");
                    sb.AppendLine($"   🌇 日落: {astronomy.GetProperty("sunset").GetString()}");
                    sb.AppendLine();
                }

                return sb.ToString();
            }
            catch (KeyNotFoundException ex)
            {
                return $"解析天气预报数据时缺少字段: {ex.Message}";
            }
        }
    }
}